package com.donleo.zuul.filter;

import com.alibaba.fastjson.JSONObject;
import com.donleo.zuul.common.CommonResult;
import com.donleo.zuul.service.UserService;
import com.donleo.zuul.utils.JwtTokenUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.jsonwebtoken.ExpiredJwtException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

/**
 * 自定义网关过滤器
 *
 * @author liangd
 * @since 2021-01-12 18:52
 */
@Component
public class LogFilter extends ZuulFilter {
    /**
     * 分割成数组
     */
    @Value("#{'${pathList}'.split(',')}")
    private List<String> pathList;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserService userService;

    /**
     * 过滤器的类型。可选值有：
     * pre - 前置过滤
     * route - 路由后过滤
     * error - 异常过滤
     * post - 远程服务调用后过滤
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 同种类的过滤器的执行顺序。
     * 按照返回值的自然升序执行。
     * 值越小，级别越高
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 哪些请求会被过滤
     */
    @Override
    public boolean shouldFilter() {
   /*     RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String requestURI = request.getRequestURI();
        //只有/api/w 开头的会被过滤
        return requestURI.startsWith("/api/w");*/
        //true 默认所有请求都会过滤
        return true;
    }

    @Override
    public Object run() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response = requestContext.getResponse();
        response.setContentType("text/html;charset=UTF-8");
        HttpServletRequest request = requestContext.getRequest();
        String uri = request.getRequestURI();
        //哪些路径可以直接放行
        boolean a = pathList.stream().anyMatch(path -> StringUtils.contains(uri, path));
        //第一种方式，从token读取权限
        //第二种方式，远程调用security服务,将判断逻辑在security服务中判断是否有访问该路径的权限
        if (a) {
            return null;
        }
        String authorization = request.getHeader("Authorization");
        if (authorization == null) {
            requestContext.setResponseBody(JSONObject.toJSONString(CommonResult.unauthorized("未登录")));
            requestContext.setSendZuulResponse(false);
            return null;
        }
        String token = StringUtils.substring(authorization, "bearer".length()).trim();
        /************************第一种方式，从token读取权限*******************************/
      /*  Set<String> auths = null;
        try {
            auths = jwtTokenUtil.getAuthsFromToken(token);
        } catch (Exception e) {
            // 处理token过期
            if (e instanceof ExpiredJwtException) {
                requestContext.setResponseBody(JSONObject.toJSONString(CommonResult.unauthorized("token已过期")));
                requestContext.setSendZuulResponse(false);
                return null;
            }
            e.printStackTrace();
        }
        //验证权限
        assert auths != null;
        boolean b = auths.stream().anyMatch(auth -> StringUtils.equals(auth, uri));
        if (!b) {
            requestContext.setResponseBody(JSONObject.toJSONString(CommonResult.forbidden("没有访问权限")));
            requestContext.setSendZuulResponse(false);
            return null;
        }
        return null;*/
        /************************第二种方式，远程调用security服务**************************/
        try {
            jwtTokenUtil.isTokenExpired(token);
        } catch (Exception e) {
            if (e instanceof ExpiredJwtException) {
                requestContext.setResponseBody(JSONObject.toJSONString(CommonResult.unauthorized("token已过期")));
                requestContext.setSendZuulResponse(false);
                return null;
            }
            e.printStackTrace();
        }
        String userCode = jwtTokenUtil.getUserCodeFromToken(token);
        CommonResult commonResult = userService.checkAuth(userCode, uri);
        long code = commonResult.getCode();
        if (code == 200) {
            return null;
        } else if (code == 500) {
            requestContext.setResponseBody(JSONObject.toJSONString(CommonResult.forbidden("没有访问权限")));
            requestContext.setSendZuulResponse(false);
            return null;
        } else {
            requestContext.setResponseBody(JSONObject.toJSONString(CommonResult.failed("未知错误")));
            requestContext.setSendZuulResponse(false);
            return null;
        }
    }
}
